import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  UploadedFile,
  UseInterceptors,
  BadRequestException,
  ParseIntPipe,
  Logger,
  Request,
  UseGuards,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';
import * as fs from 'fs';
import * as path from 'path';
import { SongService } from './song.service';
import { forwardRef } from '@nestjs/common';
import { Inject } from '@nestjs/common';
import { MyMusicService } from '../my-music/my-music.service';
import {
  CreateSongDto,
  UpdateSongDto,
  SongResponseDto,
  DailyRecommendationsQueryDto,
  SongsPaginationQueryDto,
  PaginationResponseDto,
  SongsByCategoryQueryDto,
} from './song.dto';
import { AuthGuard } from '@nestjs/passport';
// import { User } from '../user/user.entity';

// 确保uploads目录存在
const uploadsDir = './uploads';
if (!fs.existsSync(uploadsDir)) {
  try {
    fs.mkdirSync(uploadsDir, { recursive: true });
    Logger.log('上传目录已创建: ' + uploadsDir);
  } catch (error) {
    Logger.error('创建上传目录失败: ' + error.message);
  }
}

// 生成唯一文件名
const generateUniqueFilename = (req, file, callback) => {
  const randomName = Array(32)
    .fill(null)
    .map(() => Math.round(Math.random() * 16).toString(16))
    .join('');
  callback(null, `${randomName}${extname(file.originalname)}`);
};

// 创建日志记录器
const logger = new Logger('SongController');

/**
 * 歌曲控制器
 * 处理与歌曲相关的所有HTTP请求
 */
@Controller('songs')
export class SongController {
  constructor(
    private readonly songService: SongService,
    @Inject(forwardRef(() => MyMusicService))
    private readonly myMusicService: MyMusicService,
  ) {}

  /**
   * 创建新歌
   * @param createSongDto 歌曲创建数据传输对象
   * @returns 创建成功的歌曲响应数据
   */
  @Post()
  async createSong(
    @Body() createSongDto: CreateSongDto,
  ): Promise<SongResponseDto> {
    // 确保歌曲信息完整
    if (
      !createSongDto.title ||
      !createSongDto.artistId ||
      !createSongDto.audioUrl
    ) {
      throw new BadRequestException('歌曲标题、艺术家ID和音频URL为必填项');
    }
    return this.songService.createSong(createSongDto);
  }

  /**
   * 仅上传歌曲文件
   * @param file 上传的音频文件
   * @returns 上传成功的文件URL
   */
  @Post('upload-file')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        destination: './uploads', // 实际保存文件的目录
        filename: generateUniqueFilename,
      }),
      limits: {
        fileSize: 50 * 1024 * 1024, // 限制文件大小为50MB
      },
      fileFilter: (req, file, callback) => {
        try {
          // 允许的音频文件类型 - 增加AAC相关的多种MIME类型
          const allowedMimeTypes = [
            'audio/mpeg',
            'audio/wav',
            'audio/ogg',
            'audio/aac',
            'audio/x-aac', // 额外的AAC MIME类型
            'audio/mp4', // MP4容器中的AAC
            'audio/m4a', // M4A格式（通常包含AAC编码）
            'audio/flac',
            'audio/mp3',
            'audio/vnd.dlna.adts', // DLNA ADTS格式（AAC的一种容器格式）
          ];

          // 记录文件的MIME类型用于调试
          logger.debug(`上传文件的MIME类型: ${file.mimetype}`);
          logger.debug(`上传文件的原始名称: ${file.originalname}`);
          logger.debug(`上传文件的大小: ${file.size} 字节`);

          if (allowedMimeTypes.includes(file.mimetype)) {
            callback(null, true);
          } else {
            logger.warn(`拒绝上传不支持的文件类型: ${file.mimetype}`);
            callback(
              new BadRequestException(
                `不支持的文件类型 (${file.mimetype})。仅支持MP3、WAV、OGG、AAC、M4A、MP4、FLAC等音频格式。`,
              ),
              false,
            );
          }
        } catch (error) {
          logger.error(`文件过滤过程中发生错误: ${error.message}`);
          callback(new BadRequestException('文件验证失败'), false);
        }
      },
    }),
  )
  async uploadFile(
    @UploadedFile() file: Express.Multer.File,
  ): Promise<{ audioUrl: string }> {
    try {
      if (!file) {
        logger.warn('没有收到上传的文件');
        throw new BadRequestException('请上传音频文件');
      }

      // 检查文件是否成功保存
      const filePath = path.join(uploadsDir, file.filename);
      if (!fs.existsSync(filePath)) {
        logger.error(`文件保存失败，文件不存在: ${filePath}`);
        throw new BadRequestException('文件保存失败，请重试');
      }

      // 返回实际可访问的文件URL
      const audioUrl = `/uploads/${file.filename}`;
      logger.log(`文件上传成功: ${file.filename}, URL: ${audioUrl}`);

      return { audioUrl };
    } catch (error) {
      logger.error(`文件上传过程中发生错误: ${error.message}`);
      throw error; // 重新抛出错误以便全局异常过滤器处理
    }
  }

  /**
   * 创建新歌并上传文件（合并操作）
   * @param file 上传的音频文件
   * @param createSongDto 歌曲元数据
   * @returns 创建成功的歌曲响应数据
   */
  @Post('upload')
  @UseInterceptors(
    FileInterceptor('file', {
      storage: diskStorage({
        destination: './uploads', // 实际保存文件的目录
        filename: generateUniqueFilename,
      }),
      limits: {
        fileSize: 50 * 1024 * 1024, // 限制文件大小为50MB
      },
      fileFilter: (req, file, callback) => {
        try {
          // 允许的音频文件类型 - 增加AAC相关的多种MIME类型
          const allowedMimeTypes = [
            'audio/mpeg',
            'audio/wav',
            'audio/ogg',
            'audio/aac',
            'audio/x-aac', // 额外的AAC MIME类型
            'audio/mp4', // MP4容器中的AAC
            'audio/m4a', // M4A格式（通常包含AAC编码）
            'audio/flac',
            'audio/mp3',
            'audio/vnd.dlna.adts', // DLNA ADTS格式（AAC的一种容器格式）
          ];

          // 记录文件的MIME类型用于调试
          logger.debug(`上传文件的MIME类型: ${file.mimetype}`);
          logger.debug(`上传文件的原始名称: ${file.originalname}`);

          if (allowedMimeTypes.includes(file.mimetype)) {
            callback(null, true);
          } else {
            logger.warn(`拒绝上传不支持的文件类型: ${file.mimetype}`);
            callback(
              new BadRequestException(
                `不支持的文件类型 (${file.mimetype})。仅支持MP3、WAV、OGG、AAC、M4A、MP4、FLAC等音频格式。`,
              ),
              false,
            );
          }
        } catch (error) {
          logger.error(`文件过滤过程中发生错误: ${error.message}`);
          callback(new BadRequestException('文件验证失败'), false);
        }
      },
    }),
  )
  async uploadAndCreateSong(
    @UploadedFile() file: Express.Multer.File,
    @Body() createSongDto: CreateSongDto,
  ): Promise<SongResponseDto> {
    try {
      if (!file) {
        logger.warn('没有收到上传的文件');
        throw new BadRequestException('请上传音频文件');
      }

      // 确保歌曲基本信息完整
      if (!createSongDto.title || !createSongDto.artistId) {
        throw new BadRequestException('歌曲标题和艺术家ID为必填项');
      }

      // 设置音频文件URL
      createSongDto.audioUrl = `/uploads/${file.filename}`;
      if (!createSongDto.coverImageUrl) {
        createSongDto.coverImageUrl = '/default-cover.jpg';
      }

      // 检查文件是否成功保存
      const filePath = path.join(uploadsDir, file.filename);
      if (!fs.existsSync(filePath)) {
        logger.error(`文件保存失败，文件不存在: ${filePath}`);
        throw new BadRequestException('文件保存失败，请重试');
      }

      logger.log(
        `文件上传并创建歌曲成功: ${file.filename}, 歌曲标题: ${createSongDto.title}`,
      );

      return this.songService.createSong(createSongDto);
    } catch (error) {
      logger.error(`上传并创建歌曲过程中发生错误: ${error.message}`);
      throw error; // 重新抛出错误以便全局异常过滤器处理
    }
  }

  /**
   * 获取所有歌曲列表
   * @param genre 按流派筛选（可选）
   * @param artist 按艺术家筛选（可选）
   * @param album 按专辑筛选（可选）
   * @param searchTerm 搜索关键词（可选）
   * @returns 歌曲响应数据数组
   */
  @Get()
  async findAllSongs(
    @Query('genre') genre?: string,
    @Query('artist') artist?: string,
    @Query('album') album?: string,
    @Query('searchTerm') searchTerm?: string,
    @Query('page') page?: number,
    @Query('limit') limit?: number,
  ): Promise<SongResponseDto[]> {
    console.log('genre', page, limit);
    // 如果提供了page和limit参数，使用分页方法
    if (page !== undefined && limit !== undefined) {
      const result = await this.songService.findSongsWithPagination({
        page,
        limit,
        genre,
        artist,
        album,
        searchTerm,
      });
      return result.data;
    }
    // 否则返回所有数据（保持向后兼容）
    return this.songService.findAllSongs(genre, artist, album, searchTerm);
  }

  /**
   * 获取分页歌曲列表
   * @param queryDto 分页查询参数
   * @returns 分页响应数据
   */
  @Get('paginated')
  async findSongsWithPagination(
    @Query() queryDto: SongsPaginationQueryDto,
  ): Promise<PaginationResponseDto<SongResponseDto>> {
    return this.songService.findSongsWithPagination(queryDto);
  }

  /**
   * 获取歌曲列表（按分类筛选，可选）
   * @param queryDto 分类歌曲查询参数
   * @returns 分页响应数据
   * @description 如果提供categoryId，则返回该分类下的歌曲；如果不提供，则返回所有分类的歌曲
   */
  @Get('by-category')
  async findSongsByCategory(
    @Query() queryDto: SongsByCategoryQueryDto,
  ): Promise<PaginationResponseDto<SongResponseDto>> {
    return this.songService.findSongsByCategory(queryDto);
  }

  /**
   * 更新歌曲信息
   * @param id 歌曲ID
   * @param updateSongDto 歌曲更新数据传输对象
   * @returns 更新后的歌曲响应数据
   */
  @Put(':id')
  async updateSong(
    @Param('id', ParseIntPipe) id: number,
    @Body() updateSongDto: UpdateSongDto,
  ): Promise<SongResponseDto> {
    console.log('updateSongDto', updateSongDto);

    return this.songService.updateSong(id, updateSongDto);
  }

  /**
   * 删除歌曲
   * @param id 歌曲ID
   */
  @Delete(':id')
  async deleteSong(@Param('id', ParseIntPipe) id: number): Promise<void> {
    return this.songService.deleteSong(id);
  }

  /**
   * 增加歌曲播放量并可选记录用户播放历史
   * @param id 歌曲ID
   * @param req 请求对象，如果用户已登录则包含用户信息
   * @returns 操作结果消息
   */
  @Post(':id/play')
  async playSong(
    @Param('id', ParseIntPipe) id: number,
  ): Promise<{ message: string }> {
    await this.songService.incrementPlays(id);

    return { message: '播放量已增加' };
  }

  /**
   * 点赞/取消点赞歌曲
   * @param id 歌曲ID
   * @param req 请求对象，包含当前用户信息
   * @returns 点赞信息（点赞数和是否已点赞）
   */
  @Post(':id/like')
  @UseGuards(AuthGuard('jwt'))
  async likeSong(
    @Param('id', ParseIntPipe) id: number,
    @Request() req: any,
  ): Promise<{ likes: number; isLiked: boolean }> {
    const userId = req.user.id;
    console.log('点赞');
    return this.songService.toggleLike(id, userId);
  }

  /**
   * 收藏/取消收藏歌曲
   * @param id 歌曲ID
   * @param req 请求对象，包含当前用户信息
   * @returns 收藏信息（收藏数和是否已收藏）
   */
  @Post(':id/collect')
  @UseGuards(AuthGuard('jwt'))
  async collectSong(
    @Param('id', ParseIntPipe) id: number,
    @Request() req: any,
  ): Promise<{ collections: number; isCollected: boolean }> {
    const userId = req.user.id;
    return this.songService.toggleCollection(id, userId);
  }

  /**
   * 获取热门歌曲列表
   * @param limit 限制返回数量（默认50，最大200）
   * @param timeRange 时间范围筛选（可选：day、week、month）
   * @returns 热门歌曲列表
   */
  @Get('top/list')
  async getTopSongs(
    @Query('limit', new ParseIntPipe({ optional: true })) limit?: number,
    @Query('timeRange') timeRange?: 'day' | 'week' | 'month',
  ): Promise<SongResponseDto[]> {
    // 验证时间范围参数
    if (timeRange && !['day', 'week', 'month'].includes(timeRange)) {
      throw new BadRequestException('timeRange参数必须是day、week或month');
    }

    // 验证limit参数范围
    const safeLimit = limit && limit > 0 && limit <= 200 ? limit : 50;
    return this.songService.getTopSongs(safeLimit, timeRange);
  }

  /**
   * 获取趋势歌曲列表（使用综合热度算法）
   * @param limit 限制返回数量（默认50，最大200）
   * @returns 趋势歌曲列表
   */
  @Get('trending/list')
  async getTrendingSongs(
    @Query('limit', new ParseIntPipe({ optional: true })) limit?: number,
  ): Promise<SongResponseDto[]> {
    // 验证limit参数范围
    const safeLimit = limit && limit > 0 && limit <= 200 ? limit : 50;
    console.log('trending/list', safeLimit);
    return this.songService.getTrendingSongs(safeLimit);
  }

  /**
   * 查询歌曲是否被用户收藏和点赞
   * @param id 歌曲ID
   * @param req 请求对象，包含当前用户信息
   * @returns 歌曲状态信息（是否点赞、是否收藏、点赞数、收藏数）
   */
  @Get(':id/status')
  @UseGuards(AuthGuard('jwt'))
  async getSongStatus(
    @Param('id', ParseIntPipe) id: number,
    @Request() req: any,
  ): Promise<{
    isLiked: boolean;
    isCollected: boolean;
    likes: number;
    collections: number;
  }> {
    const userId = req.user.id;
    console.log('getSongStatus', userId);
    return this.songService.getSongStatus(id, userId);
  }

  /**
   * 获取每日推荐歌曲列表
   * 每天都会生成不同的推荐列表
   * @param query 查询参数对象
   * @returns 每日推荐歌曲列表
   */
  @Get('daily-recommendations')
  async getDailyRecommendations(
    @Query() query: DailyRecommendationsQueryDto,
  ): Promise<SongResponseDto[]> {
    // 手动验证和转换limit参数
    let safeLimit = 20; // 默认值
    if (query.limit) {
      const parsedLimit = parseInt(query.limit, 10);
      // 检查是否是有效数字且在有效范围内
      if (!Number.isNaN(parsedLimit) && parsedLimit > 0 && parsedLimit <= 200) {
        safeLimit = parsedLimit;
      } else {
        throw new BadRequestException('limit参数必须是有效的数字(1-200)');
      }
    }
    return this.songService.getDailyRecommendations(safeLimit);
  }

  /**
   * 根据ID获取单首歌曲详情
   * @param id 歌曲ID
   * @returns 歌曲响应数据
   */
  @Get(':id')
  async findSongById(
    @Param('id', ParseIntPipe) id: number,
  ): Promise<SongResponseDto> {
    return this.songService.findSongById(id);
  }
}
